﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Configuration;

namespace ADI.Security.Membership
{
    #region Application Definition
    public class ADISSOApplicationCollection : ICollection<RegisteredApp>
    {

        public IEnumerator<RegisteredApp> GetEnumerator()
        {
            return new ApplicationEnumerator(this);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new ApplicationEnumerator(this);
        }

        private List<RegisteredApp> innerCol;

        private bool isRO = false;

        public ADISSOApplicationCollection()
        {
            innerCol = new List<RegisteredApp>();
        }

        public RegisteredApp this[int index]
        {
            get { return (RegisteredApp)innerCol[index]; }
            set { innerCol[index] = value; }
        }

        public bool Contains(RegisteredApp item)
        {
            bool found = false;

            foreach (RegisteredApp bx in innerCol)
            {
                if (bx.Equals(item))
                {
                    found = true;
                }
            }

            return found;
        }

        public bool Contains(RegisteredApp item, EqualityComparer<RegisteredApp> comp)
        {
            bool found = false;

            foreach (RegisteredApp bx in innerCol)
            {
                if (comp.Equals(bx, item))
                {
                    found = true;
                }
            }

            return found;
        }

        public void Add(RegisteredApp item)
        {

            if (!Contains(item))
            {
                innerCol.Add(item);
            }
            else
            {
                Console.WriteLine("An Application with The same ID already exists.");
            }
        }

        public void Clear()
        {
            innerCol.Clear();
        }

        public void CopyTo(RegisteredApp[] array, int arrayIndex)
        {
            for (int i = 0; i < innerCol.Count; i++)
            {

                array[i] = (RegisteredApp)innerCol[i];
            }
        }

        public int Count
        {
            get
            {
                return innerCol.Count;
            }
        }

        public bool IsReadOnly
        {
            get { return isRO; }
        }

        public bool Remove(RegisteredApp item)
        {
            bool result = false;

            // Iterate the inner collection to 
            // find the Application to be removed.
            for (int i = 0; i < innerCol.Count; i++)
            {

                RegisteredApp curApplication = (RegisteredApp)innerCol[i];

                if (curApplication.Equals(item))
                {
                    innerCol.RemoveAt(i);
                    result = true;
                    break;
                }
            }
            return result;
        }
    }


    public class ApplicationEnumerator : IEnumerator<RegisteredApp>
    {
        private ADISSOApplicationCollection _collection;
        private int curIndex;
        private RegisteredApp curApplication;


        public ApplicationEnumerator(ADISSOApplicationCollection collection)
        {
            _collection = collection;
            curIndex = -1;
            curApplication = default(RegisteredApp);
        }

        public bool MoveNext()
        {
            //Avoids going beyond the end of the collection.
            if (++curIndex >= _collection.Count)
            {
                return false;
            }
            else
            {
                // Set current Application to next item in collection.
                curApplication = _collection[curIndex];
            }
            return true;
        }

        public void Reset() { curIndex = -1; }

        void IDisposable.Dispose() { }

        public RegisteredApp Current
        {
            get { return curApplication; }
        }


        object IEnumerator.Current
        {
            get { return Current; }
        }
    }
    #endregion

    #region Web Config Section
    public class ADISSOApplicationSection : ConfigurationSection
    {
        [ConfigurationProperty("Enabled", DefaultValue = "true", IsRequired = false)]
        public Boolean Enabled
        {
            get
            {
                return (Boolean)this["Enabled"];
            }
            set
            {
                this["Enabled"] = value;
            }
        }

        [ConfigurationProperty("add")]
        public AddElement Add
        {
            get
            {
                return (AddElement)this["add"];
            }
            set
            { this["add"] = value; }
        }
    }

    public class AddElement : ConfigurationElement
    {
        [ConfigurationProperty("connectionStringName", IsRequired = true)]
        public String connectionStringName
        {
            get
            {
                return (String)this["connectionStringName"];
            }
            set
            {
                this["connectionStringName"] = value;
            }
        }
    }
    #endregion

    #region Application Provider
    public sealed class ADISSOApplication
    {
        private ConnectionStringSettings connectionString;
        /*************************************************************************
        * User related methods
        *************************************************************************/

        public ADISSOApplication()
        {
            Initialize();
        }

        public void Initialize()
        {
            Configuration cfg = WebConfigurationManager.OpenWebConfiguration("/");
            ADISSOApplicationSection appSection = (ADISSOApplicationSection)cfg.GetSection("ADISSOApplication");

            connectionString = ConfigurationManager.ConnectionStrings[appSection.Add.connectionStringName];
        }

        public ADISSOApplicationCollection GetAllApplication(bool ActiveOnly)
        {
            ADISSOApplicationCollection _data = new ADISSOApplicationCollection();
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var apps = adc.RegisteredApp.Where(r => 1 == 1);
                if (ActiveOnly)
                    apps = adc.RegisteredApp.Where(r => r.Active == true);

                foreach (var a in apps)
                {
                    _data.Add(a);
                }
            }
            return _data;
        }

        public ADISSOApplicationCollection GetAllApplication(bool ActiveOnly, string AppNameToMatch)
        {
            ADISSOApplicationCollection _data = new ADISSOApplicationCollection();
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var apps = adc.RegisteredApp.Where(r => 1 == 1);
                if (ActiveOnly)
                    apps = adc.RegisteredApp.Where(r => r.Active == true);
                if (!string.IsNullOrEmpty(AppNameToMatch.Trim()))
                    apps = adc.RegisteredApp.Where(r => r.AppName.ToLower().Contains(AppNameToMatch.ToLower()));

                foreach (var a in apps)
                {
                    _data.Add(a);
                }
            }
            return _data;
        }


        public void CreateApplication(string AppName, string FQDN, string Description, bool Active)
        {
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var exist = adc.RegisteredApp.Where(r => r.AppName.ToLower() == AppName.ToLower()).SingleOrDefault();
                if (exist != null) throw new Exception("Un'applicazione con questo nome esiste già");
                try
                {
                    RegisteredApp ra = new RegisteredApp();
                    ra.RegisteredAppId = Guid.NewGuid();
                    ra.AppName = AppName;
                    ra.FQDN = FQDN;
                    ra.Description = Description;
                    ra.Active = Active;
                    adc.RegisteredApp.InsertOnSubmit(ra);
                    adc.SubmitChanges();
                }
                catch
                {
                    new Exception("Si è verificato un errore nella creazione dell'applicazione");
                }
            }
        }

        public void UpdateApplication(Guid RegisteredAppId, string AppName, string FQDN, string Description, bool Active)
        {
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var app = adc.RegisteredApp.Where(r => r.RegisteredAppId == RegisteredAppId).Single();
                if (app == null) throw new Exception("Si è verificato un errore nell'aggiornamento dell'applicazione");
                try
                {
                    app.AppName = AppName;
                    app.FQDN = FQDN;
                    app.Description = Description;
                    app.Active = Active;
                    adc.SubmitChanges();
                }
                catch
                {
                    new Exception("Si è verificato un errore nell'aggiornamento dell'applicazione");
                }
            }
        }

        public void DeleteApplication(Guid RegisteredAppId, bool ForceDelete)
        {
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var app = adc.RegisteredApp.Where(r => r.RegisteredAppId == RegisteredAppId).Single();
                if (app == null) throw new Exception("Si è verificato un errore nell'eliminazione dell'applicazione");

                if (ForceDelete && app.Role.Count() > 0)
                {
                    throw new Exception("Ci sono ruoli definiti per questa applicazione. Impossibile eliminare");
                }

                try
                {
                    adc.RegisteredApp.DeleteOnSubmit(app);
                    adc.SubmitChanges();
                }
                catch
                {
                    new Exception("Si è verificato un errore nella creazione dell'applicazione");
                }
            }
        }

        public string GetApplicationNameFromId(Guid RegisteredAppId)
        {
            string _name = string.Empty;
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                RegisteredApp ra = adc.RegisteredApp.Where(r => r.RegisteredAppId == RegisteredAppId).SingleOrDefault();
                if (ra == null) throw new Exception("L'applicazione passata non esite");

                _name = ra.AppName;
            }
            return _name;
        }


        public bool isValidURL(string url)
        {
            bool isValid = false;
            using (ADISSODataContext adc = new ADISSODataContext(connectionString.ConnectionString))
            {
                var app = adc.RegisteredApp.Where(r => r.FQDN.ToLower() == url.ToLower()).SingleOrDefault();
                if (app != null) isValid = app.Active;
            }
            return isValid;
        }
    }
    #endregion
}
